﻿using MvvmCross.Core.ViewModels;
using Sidvall.LogManager.UI.Entities;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;

namespace Sidvall.LogManager.UI.ViewModels
{
    public class ServerViewModel : Sidvall.LogManager.UI.ViewModels.Core.ViewModelBase
    {
        #region Public Members

        #region ActiveServerManager

        private Sidvall.LogManager.UI.Entities.ServerManager _ActiveServerManager;
        public Sidvall.LogManager.UI.Entities.ServerManager ActiveServerManager
        {
            get
            {
                return _ActiveServerManager;
            }
            set
            {
                _ActiveServerManager = value;
                RaisePropertyChanged("ActiveServerManager");
                RaisePropertyChanged("StatusMessage");
                RaisePropertyChanged("CanSave");
                RaisePropertyChanged("CanDelete");
                RaisePropertyChanged("CanConnectToServer");
            }
        }

        #endregion
        #region ActiveServerConnection

        private ServerConnection _ActiveServerConnection;
        public ServerConnection ActiveServerConnection
        {
            get
            {
                return _ActiveServerConnection;
            }
            set
            {
                if (_ActiveServerConnection != null)
                    _ActiveServerConnection.PropertyChanged -= OnActiveServerConnectionPropertyChanged;
                _ActiveServerConnection = value;
                if (_ActiveServerConnection != null)
                {
                    _ActiveServerConnection.PropertyChanged += OnActiveServerConnectionPropertyChanged;
                    this.ActiveServerManager = ServerConnection.GetServerManager(_ActiveServerConnection.ServerConnectionId);
                }
                else
                {
                    this.ActiveServerManager = null;
                }
                RaisePropertyChanged("ActiveServerConnection");
                RaisePropertyChanged("CanDeleteServer");
                RaisePropertyChanged("ServerIsVisible");
                RaisePropertyChanged("ShowRemoteConnection");
                RaisePropertyChanged("InformationIsVisible");
                RaisePropertyChanged("StatusMessage");
            }
        }

        #endregion
        #region ConnectionTypes

        private Sidvall.Data.KeyValueCollection<string, Data.ConnectionType> _ConnectionTypes;
        public Sidvall.Data.KeyValueCollection<string, Data.ConnectionType> ConnectionTypes
        {
            get
            {
                if (_ConnectionTypes == null)
                    this.ConnectionTypes = Sidvall.Data.KeyValueManager.FromEnum<Sidvall.LogManager.Data.ConnectionType>();
                return _ConnectionTypes;
            }
            set
            {
                _ConnectionTypes = value;
                RaisePropertyChanged("ConnectionTypes");
            }
        }

        #endregion
        #region ServerIsVisible

        public bool ServerIsVisible
        {
            get
            {
                if (this.ActiveServerConnection != null)
                    return true;
                return false;
            }
        }

        #endregion
        #region ShowRemoteConnection

        public bool ShowRemoteConnection
        {
            get
            {
                if (this.ActiveServerConnection == null)
                    return false;
                if (this.ActiveServerConnection.ConnectionTypeId == Data.ConnectionType.RemoteAccess)
                    return true;
                return false;
            }
        }

        #endregion
        #region InformationIsVisible

        public bool InformationIsVisible
        {
            get
            {
                if (this.ServerIsVisible)
                    return false;
                return true;
            }
        }

        #endregion
        #region UserConfiguration

        private UserConfiguration _UserConfiguration;
        public UserConfiguration UserConfiguration
        {
            get
            {
                return _UserConfiguration;
            }
            set
            {
                _UserConfiguration = value;
                RaisePropertyChanged("UserConfiguration");
            }
        }

        #endregion
        #region StatusMessage

        public string StatusMessage
        {
            get
            {
                if (this.ActiveServerManager != null)
                    return this.ActiveServerManager.StatusMessage;
                if (this.ActiveServerConnection != null)
                {
                    if (!Sidvall.LogManager.SystemContextConfig.Current.EntityFacade.ServerConnectionManager.IsValid(this.ActiveServerConnection))
                        return "Invalid";
                }
                return "Missing";
            }
        }

        #endregion
        #region CanSave

        public bool CanSave
        {
            get
            {
                if (this.ActiveServerConnection != null)
                    return this.ActiveServerConnection.DataRowStateIsDirty;
                return false;
            }
        }

        #endregion
        #region CanDelete

        public bool CanDelete
        {
            get
            {
                if (this.ActiveServerConnection != null)
                    return true;
                return false;
            }
        }

        #endregion
        #region CanConnectToServer

        public bool CanConnectToServer
        {
            get
            {
                if (this.ActiveServerConnection != null)
                    return true;
                return false;
            }
        }

        #endregion

        #region AddServerCommand

        public ICommand AddServerCommand
        {
            get
            {
                return new MvxCommand(async () => await AddServerAsync());
            }
        }

        #endregion
        #region AddServerAsync

        public async Task AddServerAsync()
        {
            ServerConnection item;

            item = new ServerConnection();
            Sidvall.LogManager.SystemContextConfig.Current.EntityFacade.ServerConnectionManager.InitializeNewValues(item, Data.ConnectionType.NetworkSqlServer);
            this.UserConfiguration.ServerConnections.Add(item);
            this.ActiveServerConnection = item;
            await SaveUserConfigurationAsync();
        }

        #endregion
        #region SaveUserConfigurationCommand

        public ICommand SaveUserConfigurationCommand
        {
            get
            {
                return new MvxCommand(async () => await SaveUserConfigurationAsync());
            }
        }

        #endregion
        #region SaveUserConfigurationAsync

        public async Task SaveUserConfigurationAsync()
        {
            Task task = null;
            int? id;

            using (var busyManager = new Sidvall.Data.BusyManager(this))
            {
                try
                {
                    id = null;
                    if (this.ActiveServerConnection != null)
                        this.ActiveServerConnection.IsLoaded = false;
                    await Sidvall.LogManager.UI.SystemContext.Current.SaveUserConfigurationAsync(this.UserConfiguration, true);
                    if (this.ActiveServerConnection != null)
                        id = this.ActiveServerConnection.ServerConnectionId;
                    this.UserConfiguration = Sidvall.LogManager.UI.SystemContext.Current.UserConfiguration;
                    if (this.UserConfiguration.ServerConnections.Count == 1)
                    {
                        this.ActiveServerConnection = this.UserConfiguration.ServerConnections[0];
                    }
                    else if (id != null)
                    {
                        this.ActiveServerConnection = (from o in this.UserConfiguration.ServerConnections
                                                       where o.ServerConnectionId == id
                                                       select o).FirstOrDefault();
                    }
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Save Error", ex);
                }
                if (task != null)
                    await task;
            }
        }

        #endregion
        #region DeleteServerCommand

        public ICommand DeleteServerCommand
        {
            get
            {
                return new MvxCommand(async () => await DeleteServerAsync());
            }
        }

        #endregion
        #region DeleteServerAsync

        public async Task DeleteServerAsync()
        {
            Task task = null;
            if (this.ActiveServerConnection == null)
                return;
            using (var busyManager = new Sidvall.Data.BusyManager(this))
            {
                try
                {
                    var message = await Sidvall.UI.SystemContext.Current.DialogManager.ShowYesNoMessageAsync("Remove Server Connection", "Are you sure?",
                        Sidvall.UI.Dialogs.MessageType.Question, false);
                    if (!message.AnswerIsYes)
                        return;
                    this.UserConfiguration.ServerConnections.Remove(this.ActiveServerConnection);
                    await SaveUserConfigurationAsync();
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Save Error", ex);
                }
                if (task != null)
                    await task;
            }
        }

        #endregion
        #region ConnectToServer

        public ICommand ConnectToServerCommand
        {
            get
            {
                return new MvxCommand(async () => await ConnectToServerAsync());
            }
        }
        public async Task ConnectToServerAsync()
        {
            Task task = null;
            int? id;

            if (this.ActiveServerConnection == null)
                return;
            try
            {
                using (var busyManager = new Sidvall.Data.BusyManager(this))
                {
                    id = null;
                    using (var manager = new Sidvall.Business.BusinessSettingsManager(this.ActiveServerConnection, Sidvall.Business.BusinessEvents.NotifyPropertyChanged))
                    {
                        this.ActiveServerConnection.IsLoaded = false;
                    }
                    await Sidvall.LogManager.UI.SystemContext.Current.LoadServerManagerAsync(this.ActiveServerConnection);
                    id = this.ActiveServerConnection.ServerConnectionId;
                    this.UserConfiguration = Sidvall.LogManager.UI.SystemContext.Current.UserConfiguration;
                    if (this.UserConfiguration.ServerConnections.Count == 1)
                    {
                        this.ActiveServerConnection = this.UserConfiguration.ServerConnections[0];
                    }
                    else if (id != null)
                    {
                        this.ActiveServerConnection = (from o in this.UserConfiguration.ServerConnections
                                                       where o.ServerConnectionId == id
                                                       select o).FirstOrDefault();
                    }
                }
                if (this.ActiveServerManager != null)
                {
                    if (this.ActiveServerManager.IsValid)
                        await Sidvall.UI.SystemContext.Current.DialogManager.ShowMessageAsync("Connection", "Connection to server was successful.", Sidvall.UI.Dialogs.MessageType.Information);
                    else
                        await Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Error", this.ActiveServerManager.InitializeException);
                }
            }
            catch (System.Exception ex)
            {
                task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Save Error", ex);
            }
            if (task != null)
                await task;
        }

        #endregion
        #region RefreshServerCommand

        public ICommand RefreshServerCommand
        {
            get
            {
                return new MvxCommand(async () => await RefreshServerAsync());
            }
        }

        #endregion
        #region RefreshServerAsync

        public async Task RefreshServerAsync()
        {
            Task task = null;
            int? id;

            using (var busyManager = new Sidvall.Data.BusyManager(this))
            {
                try
                {
                    id = null;
                    if (this.ActiveServerConnection != null)
                        id = this.ActiveServerConnection.ServerConnectionId;
                    this.UserConfiguration = await Sidvall.LogManager.UI.SystemContext.Current.LoadUserConfigurationAsync();
                    if (this.UserConfiguration.ServerConnections.Count == 1)
                    {
                        this.ActiveServerConnection = this.UserConfiguration.ServerConnections[0];
                    }
                    else if (id != null)
                    {
                        this.ActiveServerConnection = (from o in this.UserConfiguration.ServerConnections
                                                       where o.ServerConnectionId == id
                                                       select o).FirstOrDefault();
                    }
                }
                catch (System.Exception ex)
                {
                    task = Sidvall.UI.SystemContext.Current.DialogManager.ShowErrorMessageAsync("Save Error", ex);
                }
                if (task != null)
                    await task;
            }
        }

        #endregion

        #region Start

        public override void Start()
        {
            this.UserConfiguration = Sidvall.LogManager.UI.SystemContext.Current.UserConfiguration;
            if (this.UserConfiguration.ServerConnections.Count == 1)
                this.ActiveServerConnection = this.UserConfiguration.ServerConnections[0];
        }

        #endregion

        #endregion
        #region Private Members

        #region OnActiveServerConnectionPropertyChanged

        private void OnActiveServerConnectionPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            RaisePropertyChanged("ShowRemoteConnection");
            RaisePropertyChanged("CanSave");
        }

        #endregion

        #endregion
    }
}
